package com.cngphone.AnFetion.Fetion.SIPC;

import com.cngphone.AnFetion2.R;

import java.util.ArrayList;
import java.util.HashSet;

import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import android.media.MediaPlayer;

import com.cngphone.AnFetion.FetionFriend;
import com.cngphone.AnFetion.FetionSIPC;
import com.cngphone.AnFetion.FetionService;
import com.cngphone.AnFetion.FetionUri;
import com.cngphone.AnFetion.IFriendInfoChanged;
import com.cngphone.AnFetion.MiscUtil;
import com.cngphone.AnFetion.Settings;
import com.cngphone.AnFetion.Fetion.TcpSendAndReceive;
import com.cngphone.AnFetion.Fetion.TcpSendAndReceive.IPackageReceivedHandler;
import com.cngphone.AnFetion.tools.StrUtil;

public class ReserveNotify extends SIPCBase implements IPackageReceivedHandler {

    private FetionUri fetionid;
    private FetionService ctx;
    private HashSet<IFriendInfoChanged> _friendInfoChangedListener = new HashSet<IFriendInfoChanged>();

	    
    public ReserveNotify(FetionService ctx, FetionUri fetionid, TcpSendAndReceive connection,
            SerialManager serialManager) {
        super(serialManager, connection);
        this.fetionid = fetionid;
        this.ctx = ctx;
    }

	@Override
    public boolean execute() {
        // 定制接收通知包
        connection.addPackageReceivedQueue(this);
        ArrayList<FetionSIPC.HeaderPair> headers;
		StringBuilder body;
		FetionSIPC sipc;
        headers = new ArrayList<FetionSIPC.HeaderPair>();

        headers.add(new FetionSIPC.HeaderPair("F", this.fetionid.getId()));
        headers.add(new FetionSIPC.HeaderPair("I", serialManager.getISerial() + " "));
        headers.add(new FetionSIPC.HeaderPair("Q", String.valueOf(serialManager.getSubSerial()) + " SUB"));
        headers.add(new FetionSIPC.HeaderPair("N", "presence"));
        body = new StringBuilder("<args><subscription><contacts>");
        ArrayList<FetionFriend> buddies = ctx.getFriendManager().getBuddies();
        int size = buddies.size();
        for (int i = 0; i < size; i++) {
            if (!buddies.get(i).IsMobileNo) {
                body.append("<contact uri=\"").append(buddies.get(i).Uri).append("\" />");
            }
        }
        body
                .append("</contacts><presence><basic attributes=\"all\" />"
                        + "<personal attributes=\"all\" /><extended types=\"sms;location;listening;ring-back-tone\" />"
                        + "</presence></subscription></args>");
        headers.add(new FetionSIPC.HeaderPair("L", StrUtil.getLength(body)));

        sipc = new FetionSIPC("SUB fetion.com.cn SIP-C/2.0", headers, body.toString());
        if (this.SendAndReceiveResponse(sipc)) {
            try {
                if (sipc.response.getResponseCmdLine().code.equals(SIPC_RESPONSE_CODE_OK)) {
                	return true;
                } else {
                    this.onSetText("Customize friends' status fail");
                    return false;
                }
            } catch (Exception e) {
                e.printStackTrace();
                this.onSetText("Customize friends' status fail");
                return false;
            }
        } else {
            this.onSetText("Time out while getting friends info.");
            return false;
        }
    }

    public void addFriendInfoChangedListener(IFriendInfoChanged obj) {
        this._friendInfoChangedListener.add(obj);
    }

    public void removeFriendInfoChangedListener(IFriendInfoChanged obj) {
        this._friendInfoChangedListener.remove(obj);
    }

    private void onFriendInfoChanged(FetionFriend obj) {
        for (IFriendInfoChanged iic : _friendInfoChangedListener) {
            iic.Happened(obj);
        }
    }

    private void updateFriendPresence(Element event) {
        NodeList presences = event.getElementsByTagName("presence");

        for (int i1 = 0; i1 < presences.getLength(); i1++) {
            if (!(presences.item(i1) instanceof Element)) {
                continue;
            }
            Node uri = presences.item(i1).getAttributes().getNamedItem("uri");
            if (uri == null) {
                continue;
            }
            FetionFriend ff = ctx.getFriendManager().getFriend(uri.getNodeValue());
            if (ff == null) {
                continue;
            }
            Element presenceElement = (Element) presences.item(i1);
            if (presenceElement != null) {
                NodeList basicNodes = presenceElement.getElementsByTagName("basic");
                if (basicNodes.getLength() > 0) {
                    Node basicValue = basicNodes.item(0).getAttributes().getNamedItem("value");
                    if (basicValue != null) {
                        Node desc = basicNodes.item(0).getAttributes().getNamedItem("desc");
                        String s = desc == null ? null : desc.getNodeValue();
                        if (s.equals("")) s = null;
                        int oldstatus = ff.getOnlineStatusInt();
                        ff.setOnlineStatus(Integer.parseInt(basicValue.getNodeValue()), s);
                        if (oldstatus == Settings.STATUS_OFFLINE
                                && ff.getOnlineStatusInt() != Settings.STATUS_OFFLINE) {
                            MediaPlayer.create(this.ctx.getApplicationContext(), R.raw.online).start();
                        }
                    }
                }
                NodeList personals = presenceElement.getElementsByTagName("personal");
                if (personals.getLength() > 0) {
                    NamedNodeMap nnm = personals.item(0).getAttributes();
                    Node n = nnm.getNamedItem("nickname");
                    if (n != null && !"".equals(n.getNodeValue())) {
                        ff.setNickName(n.getNodeValue());
                    }
                    n = nnm.getNamedItem("impresa");
                    if (n != null && !"".equals(n.getNodeValue())) {
                        ff.impresa = n.getNodeValue();
                    }
                }
                this.onFriendInfoChanged(ff);
            }
        }
    }

    @Override
    public boolean received(FetionSIPC sipc) {
        if (sipc.isRequest()) {
            try {
                if (sipc.getRequestCmdLine().cmd.equals("BN")) {// 收到通知
                    if (sipc.GetHeaderValue("N").equals("presence")) {
                        Document dom = parseXmlDocument(sipc.body);

                        if (dom != null) {
                            Element docElement = dom.getDocumentElement();
                            if (docElement != null && docElement.getNodeName().equals("events")) {
                                NodeList event = dom.getDocumentElement().getElementsByTagName("event");
                                for (int i = 0; i < event.getLength(); i++) {
                                    Node type = event.item(i).getAttributes().getNamedItem("type");
                                    if (type != null && type.getNodeValue().equals("PresenceChanged")) {
                                        updateFriendPresence((Element) event.item(i));
                                        return true;
                                    }
                                }
                            }

                        }
                    }
                }
            } catch (DOMException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return false;
    }

}
